﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

using ETRoboConTrakingSystem;

namespace ETRobocon.RaceTraking.GamePresentation
{
    /// <summary>
    /// RunnerTimerCounterUserControl.xaml の相互作用ロジック
    /// </summary>
    public partial class RunnerTimerCounterUserControl : UserControl, ITimerCounter
    {
        public int CurrentTime
        {
            get
            {
                InternalRunnerStopWatch stopWatch = this.Resources["stopWatch"] as InternalRunnerStopWatch;
                return stopWatch.CurrentCount;
            }
            set
            {
                InternalRunnerStopWatch stopWatch = this.Resources["stopWatch"] as InternalRunnerStopWatch;
                stopWatch.CurrentCount = value;
            }
        }

        private delegate void SetCurrentCountDelegeter(int current);
        private void setCurrentCount(int current)
        {
            this.CurrentTime = current;
        }

        public void SetCurrentCount(int current)
        {
            this.Dispatcher.BeginInvoke(new SetCurrentCountDelegeter(this.setCurrentCount), new object[] { current });
        }
        public RunnerTimerCounterUserControl()
        {
            InitializeComponent();
            InternalRunnerStopWatch stopWatch = this.Resources["stopWatch"] as InternalRunnerStopWatch;
            stopWatch.Owner = this;
        }
        public void Start()
        {
            InternalRunnerStopWatch stopWatch = this.Resources["stopWatch"] as InternalRunnerStopWatch;
            stopWatch.Start();
        }

        public void Stop()
        {
            InternalRunnerStopWatch stopWatch = this.Resources["stopWatch"] as InternalRunnerStopWatch;
            stopWatch.Stop();
        }

        //private Storyboard _storyBoard;

        public void AlertStart()
        {
            /*
            if (false)
            {
                NameScope.SetNameScope(this, new NameScope());
                SolidColorBrush brush = this.borderBG.Background as SolidColorBrush;
                this.RegisterName("AlertBrush", brush);
                ColorAnimationUsingKeyFrames colorAnimation = new ColorAnimationUsingKeyFrames();
                colorAnimation.Duration = TimeSpan.FromSeconds(16);

                colorAnimation.KeyFrames.Add(
                    new LinearColorKeyFrame(Colors.Red, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(15))));
                colorAnimation.KeyFrames.Add(
                    new LinearColorKeyFrame(Colors.DarkBlue, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));

                Storyboard.SetTargetName(colorAnimation, "AlertBrush");
                Storyboard.SetTargetProperty(colorAnimation, new PropertyPath(SolidColorBrush.ColorProperty));

                if (false)
                {
                    DoubleAnimationUsingKeyFrames blinkAnimation = new DoubleAnimationUsingKeyFrames();
                    blinkAnimation.BeginTime = TimeSpan.FromSeconds(15);
                    blinkAnimation.Duration = TimeSpan.FromSeconds(30);
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(6))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(8))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(10))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(11))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(12))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(12.5))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(13))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(13.5))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(14))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(14.5))));
                    blinkAnimation.KeyFrames.Add(
                        new LinearDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(15))));
                    Storyboard.SetTargetName(blinkAnimation, "borderBG");
                    Storyboard.SetTargetProperty(blinkAnimation, new PropertyPath(Border.OpacityProperty));
                }
                _storyBoard = new Storyboard();
                _storyBoard.Children.Add(colorAnimation);
                //_storyBoard.Children.Add(blinkAnimation);

                _storyBoard.Begin(this);
            }
            */
            Storyboard sb = this.Resources["BlinkStoryboard"] as Storyboard;
            if (sb != null)
            {
                sb.Begin(this);
            }
        }

        public void AlertStop()
        {
            //不要なコードのためコメントアウト
            /*
            if (false)
            {
                if (_storyBoard != null)
                {
                    _storyBoard.Stop(this);
                    _storyBoard.Remove(this);
                    _storyBoard = null;
                }
            }
            */
            Storyboard sb = this.Resources["BlinkStoryboard"] as Storyboard;
            sb.Stop(this);
            //this.alertBlush.Color = Colors.DarkBlue;
        }

        public void ResetCounter()
        {
            TimeCountFaceInfo info = this.Resources["FaceInfo"] as TimeCountFaceInfo;
            info.Brush = Colors.DarkBlue;
            CurrentTime = 0;
        }

        public void SetCounter(int current)
        {
            TimeCountFaceInfo info = this.Resources["FaceInfo"] as TimeCountFaceInfo;
            CurrentTime = current;
        }

        public delegate int getCurrentTimeCountDelegate();
        private int getCurrentTImeCount()
        {
            //    InternalRunnerStopWatch stopWatch = this.Resources["stopWatch"] as InternalRunnerStopWatch;
            //  return stopWatch.CurrentCount;
            return InternalRunnerStopWatch.CurrentTimeCount;
        }
        public int GetCurrentTimeCount()
        {
            Object ret = this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new getCurrentTimeCountDelegate(getCurrentTImeCount));
            return (int)ret;
        }
    }

    public class InternalRunnerStopWatch : INotifyPropertyChanged
    {
        private RunnerTimerCounterUserControl _owner;

        private int _minH = 0;
        private int _minL = 0;
        private int _secH = 0;
        private int _secL = 0;
        private int _secD = 0;

        private int currentCount = 0;
        public static int CurrentTimeCount;

        public RunnerTimerCounterUserControl Owner
        {
            set { _owner = value; }
            get { return _owner; }
        }


        public int MinH
        {
            get { return _minH; }
            set
            {
                _minH = value;
                OnPropertyChanged("MinH");
            }
        }
        public int MinL
        {
            get { return _minL; }
            set
            {
                _minL = value;
                OnPropertyChanged("MinL");
            }
        }
        public int SecH
        {
            get { return _secH; }
            set
            {
                _secH = value;
                OnPropertyChanged("SecH");
            }
        }
        public int SecL
        {
            get { return _secL; }
            set
            {
                _secL = value;
                OnPropertyChanged("SecL");
            }
        }
        public int SecD
        {
            get { return _secD; }
            set
            {
                _secD = value;
                OnPropertyChanged("SecD");
            }
        }

        public int CurrentCount
        {
            get { return currentCount; }
            set
            {
                currentCount = value;
                CurrentTimeCount = value;
                UpdateValues();
                OnPropertyChanged("CurrentCount");
            }

        }

        private System.Threading.Timer myTimer = null;
        private long startTick = 0;
        private bool alerting = false;

        public delegate void UpdateCurrentCountDelegate(int count);
        public void UpdateCurrentCount(int count)
        {
            CurrentCount = count;
            if (alerting == false)
            {
                if (count >= 900)
                {
                    alerting = true;
                    Owner.AlertStart();
                }
            }
        }

        public InternalRunnerStopWatch()
        {
        }

        private void UpdateValues()
        {
            SecD = currentCount % 10;
            currentCount /= 10;
            int sec = currentCount % 60;
            SecL = sec % 10;
            sec /= 10;
            SecH = sec;
            currentCount /= 60;
            MinL = currentCount % 10;
            currentCount /= 10;
            MinH = currentCount % 10;
        }

        private long unitTick = 1000000;
        public void Interval(object o)
        {
            if (measuring)
            {
                long duration = (System.DateTime.Now.Ticks / unitTick) - startTick;
                if (duration <= 1200)
                {
                    _owner.Dispatcher.BeginInvoke(
                        System.Windows.Threading.DispatcherPriority.Normal,
                        new UpdateCurrentCountDelegate(UpdateCurrentCount),
                        (int)duration);
                }
                else
                {
                    myTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
                    myTimer.Dispose();
                    myTimer = null;
                    alerting = false;
                    Owner.AlertStop();
                }
            }
        }

        private bool measuring = false;

        public void Start()
        {
            if (myTimer == null)
            {
                startTick = System.DateTime.Now.Ticks / unitTick;
                myTimer = new System.Threading.Timer(Interval, this, 100, 100);
                measuring = true;
            }
        }

        public void Stop()
        {
            if (myTimer != null)
            {
                measuring = false;
                myTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
                myTimer.Dispose();
                myTimer = null;
                Owner.AlertStop();
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

    }

}
